#include "config_read.hpp"
#include <filesystem>
#include <iostream>

namespace config {

/**
 * @brief 获取配置读取器的单例实例
 * @return ConfigReader& 配置读取器的引用
 */
ConfigReader& ConfigReader::getInstance() {
    static ConfigReader instance;
    return instance;
}

/**
 * @brief 初始化配置读取器
 * @param env 环境名称
 * @return bool 初始化是否成功
 */
bool ConfigReader::init(const std::string& env) {
    // 加载所有配置文件
    std::vector<std::string> configFiles = {
        configDir_ + "/software.yaml",
        configDir_ + "/camera.yaml",
        configDir_ + "/algorithm.yaml",
        configDir_ + "/network.yaml",
        configDir_ + "/display.yaml"
    };

    // 检查并加载每个配置文件
    for (const auto& file : configFiles) {
        if (!std::filesystem::exists(file)) {
            std::cerr << "Config file not found: " << file << std::endl;
            return false;
        }
        try {
            YAML::Node node = YAML::LoadFile(file);
            // 合并配置
            if (config_.IsNull()) {
                config_ = node;
            } else {
                for (const auto& it : node) {
                    config_[it.first.as<std::string>()] = it.second;
                }
            }
        } catch (const YAML::Exception& e) {
            std::cerr << "Error loading config file " << file << ": " << e.what() << std::endl;
            return false;
        }
    }

    // 解析配置到结构体
    parseConfig();
    return true;
}

/**
 * @brief 加载指定的配置文件
 * @param filename 配置文件路径
 * @return bool 加载是否成功
 * @throws YAML::Exception 如果文件不存在或格式错误
 */
bool ConfigReader::loadConfig(const std::string& filename) {
    try {
        YAML::Node node = YAML::LoadFile(filename);
        if (config_.IsNull()) {
            config_ = node;
        } else {
            for (const auto& it : node) {
                config_[it.first.as<std::string>()] = it.second;
            }
        }
        return true;
    } catch (const YAML::Exception& e) {
        std::cerr << "Error loading config file: " << filename << std::endl;
        std::cerr << "Error: " << e.what() << std::endl;
        return false;
    }
}

/**
 * @brief 获取指定键的YAML节点
 * @param key 配置键
 * @return YAML::Node 对应的YAML节点,如果不存在返回空节点
 */
YAML::Node ConfigReader::getNode(const std::string& key) const {
    try {
        return config_[key];
    } catch (const YAML::Exception& e) {
        return YAML::Node();
    }
}

/**
 * @brief 解析配置到结构体
 * @note 将YAML配置解析到对应的配置结构体中,使用默认值处理缺失的配置项
 */
void ConfigReader::parseConfig() {
    // 解析软件配置
    if (auto node = getNode("software")) {
        if (auto basic = node["basic"]) {
            softwareConfig_.basic.version = basic["version"].as<std::string>(softwareConfig_.basic.version);
            softwareConfig_.basic.name = basic["name"].as<std::string>(softwareConfig_.basic.name);
            softwareConfig_.basic.env = basic["env"].as<std::string>(softwareConfig_.basic.env);
        }
        if (auto system = node["system"]) {
            softwareConfig_.system.thread_pool_size = system["thread_pool_size"].as<int>(softwareConfig_.system.thread_pool_size);
            softwareConfig_.system.gpu_id = system["gpu_id"].as<int>(softwareConfig_.system.gpu_id);
            softwareConfig_.system.cuda_enabled = system["cuda_enabled"].as<bool>(softwareConfig_.system.cuda_enabled);
            softwareConfig_.system.memory_limit = system["memory_limit"].as<int>(softwareConfig_.system.memory_limit);
        }
    }

    // 解析相机配置
    if (auto node = getNode("camera")) {
        cameraConfig_.type = node["type"].as<std::string>(cameraConfig_.type);
        cameraConfig_.device_id = node["device_id"].as<int>(cameraConfig_.device_id);
        cameraConfig_.serial_number = node["serial_number"].as<std::string>(cameraConfig_.serial_number);
        
        if (auto resolution = node["resolution"]) {
            cameraConfig_.resolution.width = resolution["width"].as<int>(cameraConfig_.resolution.width);
            cameraConfig_.resolution.height = resolution["height"].as<int>(cameraConfig_.resolution.height);
        }
        
        cameraConfig_.frame_rate = node["frame_rate"].as<int>(cameraConfig_.frame_rate);
    }

    // 解析算法配置
    if (auto node = getNode("algorithm")) {
        if (auto model = node["model"]) {
            algorithmConfig_.model.name = model["name"].as<std::string>(algorithmConfig_.model.name);
            algorithmConfig_.model.type = model["type"].as<std::string>(algorithmConfig_.model.type);
            algorithmConfig_.model.path = model["path"].as<std::string>(algorithmConfig_.model.path);
            algorithmConfig_.model.device = model["device"].as<std::string>(algorithmConfig_.model.device);
            algorithmConfig_.model.batch_size = model["batch_size"].as<int>(algorithmConfig_.model.batch_size);
            algorithmConfig_.model.precision = model["precision"].as<std::string>(algorithmConfig_.model.precision);
        }
    }

    // 解析网络配置
    if (auto node = getNode("network")) {
        if (auto tcp = node["tcp"]) {
            if (auto server = tcp["server"]) {
                networkConfig_.tcp.server.enabled = server["enabled"].as<bool>(networkConfig_.tcp.server.enabled);
                networkConfig_.tcp.server.ip = server["ip"].as<std::string>(networkConfig_.tcp.server.ip);
                networkConfig_.tcp.server.port = server["port"].as<int>(networkConfig_.tcp.server.port);
                networkConfig_.tcp.server.max_connections = server["max_connections"].as<int>(networkConfig_.tcp.server.max_connections);
            }
        }
    }

    // 解析显示配置
    if (auto node = getNode("display")) {
        if (auto window = node["window"]) {
            displayConfig_.window.title = window["title"].as<std::string>(displayConfig_.window.title);
            displayConfig_.window.width = window["width"].as<int>(displayConfig_.window.width);
            displayConfig_.window.height = window["height"].as<int>(displayConfig_.window.height);
            displayConfig_.window.fullscreen = window["fullscreen"].as<bool>(displayConfig_.window.fullscreen);
            displayConfig_.window.fps = window["fps"].as<int>(displayConfig_.window.fps);
        }
        if (auto content = node["content"]) {
            displayConfig_.content.show_fps = content["show_fps"].as<bool>(displayConfig_.content.show_fps);
            displayConfig_.content.show_detection = content["show_detection"].as<bool>(displayConfig_.content.show_detection);
            displayConfig_.content.show_tracking = content["show_tracking"].as<bool>(displayConfig_.content.show_tracking);
            displayConfig_.content.show_statistics = content["show_statistics"].as<bool>(displayConfig_.content.show_statistics);
        }
    }
}

} // namespace config
